home *** CD-ROM | disk | FTP | other *** search
/ Clickx 115 / Clickx 115.iso / software / tools / windows / tails-i386-0.16.iso / live / filesystem.squashfs / usr / share / inkscape / extensions / measure.py < prev    next >
Encoding:
Python Source  |  2010-03-12  |  7.5 KB  |  178 lines

  1. #!/usr/bin/env python 
  2. '''
  3. This extension module can measure arbitrary path and object length
  4. It adds a text to the selected path containing the length in a
  5. given unit.
  6.  
  7. Copyright (C) 2006 Georg Wiora
  8. Copyright (C) 2006 Nathan Hurst
  9. Copyright (C) 2005 Aaron Spike, aaron@ekips.org
  10.  
  11. This program is free software; you can redistribute it and/or modify
  12. it under the terms of the GNU General Public License as published by
  13. the Free Software Foundation; either version 2 of the License, or
  14. (at your option) any later version.
  15.  
  16. This program is distributed in the hope that it will be useful,
  17. but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19. GNU General Public License for more details.
  20.  
  21. You should have received a copy of the GNU General Public License
  22. along with this program; if not, write to the Free Software
  23. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  24.  
  25. TODO:
  26.  * should use the standard attributes for text
  27.  * Implement option to keep text orientation upright 
  28.     1. Find text direction i.e. path tangent,
  29.     2. check direction >90 or <-90 Degrees
  30.     3. rotate by 180 degrees around text center
  31. '''
  32. import inkex, simplestyle, simplepath, sys, cubicsuperpath, bezmisc, locale
  33. # Set current system locale
  34. locale.setlocale(locale.LC_ALL, '')
  35.  
  36. def numsegs(csp):
  37.     return sum([len(p)-1 for p in csp])
  38. def interpcoord(v1,v2,p):
  39.     return v1+((v2-v1)*p)
  40. def interppoints(p1,p2,p):
  41.     return [interpcoord(p1[0],p2[0],p),interpcoord(p1[1],p2[1],p)]
  42. def pointdistance((x1,y1),(x2,y2)):
  43.     return math.sqrt(((x2 - x1) ** 2) + ((y2 - y1) ** 2))
  44. def bezlenapprx(sp1, sp2):
  45.     return pointdistance(sp1[1], sp1[2]) + pointdistance(sp1[2], sp2[0]) + pointdistance(sp2[0], sp2[1])
  46. def tpoint((x1,y1), (x2,y2), t = 0.5):
  47.     return [x1+t*(x2-x1),y1+t*(y2-y1)]
  48. def cspbezsplit(sp1, sp2, t = 0.5):
  49.     m1=tpoint(sp1[1],sp1[2],t)
  50.     m2=tpoint(sp1[2],sp2[0],t)
  51.     m3=tpoint(sp2[0],sp2[1],t)
  52.     m4=tpoint(m1,m2,t)
  53.     m5=tpoint(m2,m3,t)
  54.     m=tpoint(m4,m5,t)
  55.     return [[sp1[0][:],sp1[1][:],m1], [m4,m,m5], [m3,sp2[1][:],sp2[2][:]]]
  56. def cspbezsplitatlength(sp1, sp2, l = 0.5, tolerance = 0.001):
  57.     bez = (sp1[1][:],sp1[2][:],sp2[0][:],sp2[1][:])
  58.     t = bezmisc.beziertatlength(bez, l, tolerance)
  59.     return cspbezsplit(sp1, sp2, t)
  60. def cspseglength(sp1,sp2, tolerance = 0.001):
  61.     bez = (sp1[1][:],sp1[2][:],sp2[0][:],sp2[1][:])
  62.     return bezmisc.bezierlength(bez, tolerance)    
  63. def csplength(csp):
  64.     total = 0
  65.     lengths = []
  66.     for sp in csp:
  67.         lengths.append([])
  68.         for i in xrange(1,len(sp)):
  69.             l = cspseglength(sp[i-1],sp[i])
  70.             lengths[-1].append(l)
  71.             total += l            
  72.     return lengths, total
  73.  
  74. class Length(inkex.Effect):
  75.     def __init__(self):
  76.         inkex.Effect.__init__(self)
  77.         self.OptionParser.add_option("-f", "--fontsize",
  78.                         action="store", type="int", 
  79.                         dest="fontsize", default=20,
  80.                         help="Size of length lable text in px")
  81.         self.OptionParser.add_option("-o", "--offset",
  82.                         action="store", type="float", 
  83.                         dest="offset", default=-6,
  84.                         help="The distance above the curve")
  85.         self.OptionParser.add_option("-u", "--unit",
  86.                         action="store", type="string", 
  87.                         dest="unit", default="mm",
  88.                         help="The unit of the measurement")
  89.         self.OptionParser.add_option("-p", "--precision",
  90.                         action="store", type="int", 
  91.                         dest="precision", default=2,
  92.                         help="Number of significant digits after decimal point")
  93.         self.OptionParser.add_option("-s", "--scale",
  94.                         action="store", type="float", 
  95.                         dest="scale", default=1,
  96.                         help="The distance above the curve")
  97.         self.OptionParser.add_option("-r", "--orient",
  98.                         action="store", type="inkbool", 
  99.                         dest="orient", default=True,
  100.                         help="Keep orientation of text upright")
  101.         self.OptionParser.add_option("--tab",
  102.                         action="store", type="string", 
  103.                         dest="tab", default="sampling",
  104.                         help="The selected UI-tab when OK was pressed") 
  105.         self.OptionParser.add_option("--measurehelp",
  106.                         action="store", type="string", 
  107.                         dest="measurehelp", default="",
  108.                         help="dummy") 
  109.                         
  110.     def effect(self):
  111.         # get number of digits
  112.         prec = int(self.options.precision)
  113.         # loop over all selected paths
  114.         for id, node in self.selected.iteritems():
  115.             if node.tag == inkex.addNS('path','svg'):
  116.                 self.group = inkex.etree.SubElement(node.getparent(),inkex.addNS('text','svg'))
  117.                 
  118.                 t = node.get('transform')
  119.                 # Removed to fix LP #308183 
  120.                 # (Measure Path text shifted when used with a copied object)
  121.                 #if t:
  122.                 #    self.group.set('transform', t)
  123.  
  124.  
  125.                 a =[]
  126.                 p = cubicsuperpath.parsePath(node.get('d'))
  127.                 num = 1
  128.                 slengths, stotal = csplength(p)
  129.                 ''' Wio: Umrechnung in unit '''
  130.                 if self.options.unit=="mm":
  131.                     factor=25.4/90.0        # px->mm
  132.                 elif self.options.unit=="pt":
  133.                     factor=0.80             # px->pt
  134.                 elif self.options.unit=="cm":
  135.                     factor=25.4/900.0       # px->cm
  136.                 elif self.options.unit=="m":
  137.                     factor=25.4/90000.0     # px->m
  138.                 elif self.options.unit=="km":
  139.                     factor=25.4/90000000.0  # px->km
  140.                 elif self.options.unit=="in":
  141.                     factor=1.0/90.0         # px->in
  142.                 elif self.options.unit=="ft":
  143.                     factor=1.0/90.0/12.0    # px->ft
  144.                 elif self.options.unit=="yd":
  145.                     factor=1.0/90.0/36.0    # px->yd
  146.                 else :
  147.                     ''' Default unit is px'''
  148.                     factor=1
  149.                     self.options.unit="px"
  150.                     
  151.                 # Format the length as string
  152.                 lenstr = locale.format("%(len)25."+str(prec)+"f",{'len':round(stotal*factor*self.options.scale,prec)}).strip()
  153.                 self.addTextOnPath(self.group,0, 0,lenstr+' '+self.options.unit, id, self.options.offset)
  154.  
  155.  
  156.     def addTextOnPath(self,node,x,y,text, id,dy=0):
  157.                 new = inkex.etree.SubElement(node,inkex.addNS('textPath','svg'))
  158.                 s = {'text-align': 'center', 'vertical-align': 'bottom',
  159.                     'text-anchor': 'middle', 'font-size': str(self.options.fontsize),
  160.                     'fill-opacity': '1.0', 'stroke': 'none',
  161.                     'font-weight': 'normal', 'font-style': 'normal', 'fill': '#000000'}
  162.                 new.set('style', simplestyle.formatStyle(s))
  163.                 new.set(inkex.addNS('href','xlink'), '#'+id)
  164.                 new.set('startOffset', "50%")
  165.                 new.set('dy', str(dy)) # dubious merit
  166.                 #new.append(tp)
  167.                 new.text = str(text)
  168.                 #node.set('transform','rotate(180,'+str(-x)+','+str(-y)+')')
  169.                 node.set('x', str(x))
  170.                 node.set('y', str(y))
  171.  
  172. if __name__ == '__main__':
  173.     e = Length()
  174.     e.affect()
  175.  
  176.  
  177. # vim: expandtab shiftwidth=4 tabstop=8 softtabstop=4 encoding=utf-8 textwidth=99
  178.